package com.aboverock.core.aop;

import com.aboverock.common.enums.LogTypeEnum;
import com.aboverock.core.security.enums.SecurityTypeEnum;
import com.aboverock.module.system.domain.Log;
import com.aboverock.module.system.service.LogService;
import java.net.InetAddress;
import java.util.Date;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * 使用AspectJ实现定时任务日志AOP.
 *
 * @author Rock Wang
 */
@Component
@Aspect
public class TimedTaskExceptionLogAspect {

    private static Logger logger = LoggerFactory.getLogger(TimedTaskExceptionLogAspect.class);

    @Autowired
    private LogService logService;

    @Pointcut("@annotation(timedTaskLog)")
    public void timedTaskServicePointcut(TimedTaskLog timedTaskLog) {

    }

    @Around("timedTaskServicePointcut(timedTaskLog)")
    public void doSecurityLog(ProceedingJoinPoint joinPoint, TimedTaskLog timedTaskLog) throws Throwable {
        saveLog(joinPoint, timedTaskLog);
    }

    /**
     * 保存日志.
     *
     * @param joinPoint 切入点
     * @param timedTaskLog the timed task log
     * @throws Throwable the throwable
     * @see SecurityTypeEnum
     */
    public void saveLog(ProceedingJoinPoint joinPoint, TimedTaskLog timedTaskLog) throws Throwable {
        Long startTime = System.currentTimeMillis();
        // 执行方法
        StringBuilder details = new StringBuilder(timedTaskLog.value());
        try {
            joinPoint.proceed();
        } catch (Throwable e) {
            e.printStackTrace();
            details.append("{Exception:").append(e.getMessage()).append("}");
        } finally {
            Long end = System.currentTimeMillis();
            
            Log log = new Log();
            String loginName = "system";
            log.setLoginName(loginName);
            log.setType(LogTypeEnum.TIMEDTASK.getValue());
            
            String ip = InetAddress.getLocalHost().getHostAddress();
            log.setIp(ip);
            log.setBrowserType("Unknown");
            log.setRequest(joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
            log.setRequestTime(new Date(startTime));
            log.setOperationTime(String.valueOf((end - startTime) / 1000.0));
            log.setDetails(details.toString());
            if (logger.isDebugEnabled()) {
                logger.debug("user:{}, request url：{} ,  time-consuming：{}s, exception：{}.",
                        new Object[] { loginName, log.getRequest(), log.getOperationTime(),
                            log.getDetails() });
            }
            logService.save(log);
        }
    }

    protected Throwable findRootExceptionThrowable(Exception e) {
        Throwable rootCause = e;

        while (rootCause.getCause() != null) {
            rootCause = rootCause.getCause();
        }
        return rootCause;
    }
}
